class EventBus {
    constructor() {
        this.events = {};
    }

    // 常规认知的多处理器订阅入口
    $on(type, handler, isKeep) {
        return this.on(type, handler, isKeep, false);
    }

    /**
     * @param {any} type 事件名称
     * @param {any} handler 事件处理器 暂时支持一个事件只有一个处理器
     * @param {any} isKeep 是否保持常驻不被消费
     * @param {any} singleHandler 一个事件名称只对应一个处理器，为了兼容旧版单处理器逻辑，默认值是true
     * @returns
     */
    on(type, handler, isKeep = false, singleHandler = true) {
        if (singleHandler) {
            this.events[type] = [{
                handler,
                isKeep
            }];
            return this;
        }

        if (!this.events[type]) {
            this.events[type] = [];
        }
        this.events[type].push({
            handler,
            isKeep
        });
        return this;
    }

    $off(type, handler) {
        return this.off(type, handler);
    }

    //取消订阅事件
    off(type, handler) {
        if (!type) {
            return this;
        }
        const cbs = this.events[type];
        if (!cbs) {
            return this;
        }
        if (!handler) {
            this.events[type] = null;
            return this;
        }

        let cb;
        let i = cbs.length - 1;
        while (i >= 0) {
            cb = cbs[i];
            if (cb.handler === handler || cb === handler) {
                cbs.splice(i, 1);
                break;
            }
            i -= 1;
        }

        return this;
    }

    $emit(...args) {
        return this.emit(...args);
    }

    //触发事件
    emit(type, ...args) {
        const cbs = this.events[type];
        if (!cbs) {
            return this;
        }
        let cb;
        for (let i = 0, len = cbs.length; i < len; i += 1) {
            cb = cbs[i];
            if (cb.handler) {
                if (!cb.isKeep) {
                    this.off(type, cb.handler);
                }
                cb.handler.apply(this, args);
            }
        }
        return this;
    }
}

const eventBus = new EventBus();

export { EventBus };
export default eventBus;